package com.example.backend.controller.user;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.backend.dto.request.PageUserDto;
import com.example.backend.dto.request.UpdateUserInfo;
import com.example.backend.entitly.mysql.user.Users;
import com.example.backend.enums.ResultCodeEnum;
import com.example.backend.service.mysql.user.UsersService;
import com.example.backend.utils.DateUtils;
import com.example.backend.utils.ResultJson;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@Tag(name = "管理员 - 用户管理", description = "仅管理员可用的用户管理接口")
@RequestMapping("/api/admin/user")
@RequiredArgsConstructor
@Validated
@Transactional(rollbackFor = Exception.class)
public class UserAdminController {

    private final UsersService userService;

    static boolean deleteTime(Users byId) {
        LocalDate deletedDate = DateUtils.toLocalDate(byId.getDeletedAt());
        LocalDate today = LocalDate.now();
        long daysBetween = deletedDate.until(today, ChronoUnit.DAYS);
        return daysBetween > 7;
    }

    /**
     * 分页查看所有用户（需要 user:list 权限）
     */
    @PreAuthorize("hasAuthority('admin:list')")
    @GetMapping("/list")
    public ResultJson<?> listAllUsers(PageUserDto pageUserDto) {
        Page<Users> usersPage = userService.pageListByUser(pageUserDto);
        return ResultJson.success(usersPage);
    }

    /**
     * 查看某个用户详情（需要 user:detail-any 权限）
     */
    @PreAuthorize("hasAuthority('admin:detail-any')")
    @GetMapping("/{userId}")
    public ResultJson<?> getUserById(@PathVariable Long userId) {
        Users user = userService.getById(userId);
        if (user == null) {
            return ResultJson.fail(ResultCodeEnum.USER_NOT_EXIST.getCode(), ResultCodeEnum.USER_NOT_EXIST.getMessage());
        }
        return ResultJson.success(user);
    }

    /**
     * 删除任意用户（需要 user:delete-any 权限）
     */
    @PreAuthorize("hasAuthority('admin:delete-any')")
    @DeleteMapping("/{userId}")
    // Todo: 2023/9/23 删除用户
    public ResultJson<?> deleteUser(@PathVariable Long userId) {
        Boolean success = userService.removeByUserId(userId);
        if (!success) {
            return ResultJson.fail(ResultCodeEnum.USER_DELETE_FAIL.getCode(), ResultCodeEnum.USER_DELETE_FAIL.getMessage());
        }
        return ResultJson.success("删除成功，可在一段时间内恢复");
    }

    /**
     * 物理删除用户
     */
    @PreAuthorize("hasAuthority('admin:delete-any')")
    @DeleteMapping("/{userId}/delete")
    public ResultJson<?> deleteUserPermanently(@PathVariable Long userId) {
        Users byRemoveId = userService.getByRemoveId(userId);
        if (byRemoveId == null) {
            return ResultJson.fail(ResultCodeEnum.USER_NOT_DELETED.getCode(), ResultCodeEnum.USER_NOT_DELETED.getMessage());
        }
        Boolean success = userService.removeByPhysicsId(userId);
        if (!success) {
            return ResultJson.fail(ResultCodeEnum.USER_DELETE_FAIL.getCode(), ResultCodeEnum.USER_DELETE_FAIL.getMessage());
        }
        return ResultJson.success("永久删除成功");
    }

    /**
     * 恢复任意用户（需要 user:restore 权限）
     */
    @PreAuthorize("hasAuthority('admin:restore')")
    @PutMapping("/{userId}/restore")
    // Todo: 2023/9/23 恢复用户
    public ResultJson<?> restoreUser(@PathVariable Long userId) {
        Boolean success = userService.cancelRemove(userId);
        if (!success) {
            return ResultJson.fail(ResultCodeEnum.USER_RESTORE_FAIL.getCode(), ResultCodeEnum.USER_RESTORE_FAIL.getMessage());
        }
        return ResultJson.success("恢复成功");
    }

    /**
     * 修改其他用户信息（需要 user:update-any 权限）
     */
    @PreAuthorize("hasAuthority('user:update-any')")
    @PutMapping("/{userId}/update")
    public ResultJson<?> updateUser(@PathVariable Long userId, @RequestBody UpdateUserInfo updateUserInfo) {
        updateUserInfo.setUserId(userId);
        Users convert = Convert.convert(Users.class, updateUserInfo);
        userService.saveOrUpdate(convert);
        return ResultJson.success("修改成功");
    }

    /**
     * 批量删除
     */
    @PreAuthorize("hasAuthority('admin:delete-any')")
    @DeleteMapping("/batch")
    // Todo: 2023/9/23 删除用户
    public ResultJson<?> deleteUsers(@RequestBody Long[] userIds) {
        List<Boolean> collect = Arrays.stream(userIds).map(userService::removeByUserId).collect(Collectors.toList());
        if (collect.contains(false)) {
            long failCount = Arrays.stream(userIds)
                    .map(userService::removeByUserId)
                    .filter(b -> !b)
                    .count();
            return ResultJson.fail(ResultCodeEnum.USER_DELETE_FAIL.getCode(), failCount + "个用户删除失败");
        }
        return ResultJson.success("删除成功");
    }

    /**
     * 批量更新
     */
    @PreAuthorize("hasAuthority('admin:update-any')")
    @PutMapping("/batch")
    public ResultJson<?> updateUsers(@RequestBody List<UpdateUserInfo> updateUserInfos) {
        List<Users> collect = new ArrayList<>();
        for (UpdateUserInfo updateUserInfo : updateUserInfos) {
            Users user = Convert.convert(Users.class, updateUserInfo);
            if (user == null) {
                return ResultJson.fail(ResultCodeEnum.USER_UPDATE_FAIL.getCode(), "用户信息转换失败");
            }
            collect.add(user);
        }
        boolean b = userService.saveOrUpdateBatch(collect);
        if (!b) {
            return ResultJson.fail(ResultCodeEnum.USER_UPDATE_FAIL.getCode(), ResultCodeEnum.USER_UPDATE_FAIL.getMessage());
        }
        return ResultJson.success("修改成功");
    }

    /**
     * 批量恢复
     */
    @PreAuthorize("hasAuthority('admin:restore')")
    @PutMapping("/batch/restore")
    public ResultJson<?> restoreUsers(@RequestBody Long[] userIds) {
        // Todo: 2023/9/23 恢复用户
        List<Long> successUserIds = new ArrayList<>();
        for (Long userId : userIds) {

            Users user = userService.getByRemoveId(userId);
            if (user != null && deleteTime(user)) {
                userService.cancelRemove(userId);
                successUserIds.add(userId);
            }
        }

        return ResultJson.success("以下用户恢复成功：" + successUserIds);
    }
}
